/*-----------------------------------------------------------------------------
The contents of this file are subject to the Mozilla Public License
Version 1.1 (the "License"); you may not use this file except in
compliance with the License.You may obtain a copy of the License at
http://www.mozilla.org/MPL/MPL-1.1.html
	
Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
License for the specific language governing rights and limitations
under the License.
	
The Original Code is Fever RS ( ActionScript 3 ) Framework code.
	
The Initial Developer of the Original Code is Romain Ecarnot.
Portions created by Initial Developer are Copyright (C) 2006
the Initial Developer. All Rights Reserved.
	
Contributor(s):
	
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-----------------------------------------------------------------------------*/

package fever.utils 
{
	import fever.log.FeverDebug;		

	/**
	 * Array collection methods.
	 * 
	 * @author Romain Ecarnot
	 */
	final public class ArrayUtil 
	{

		//--------------------------------------------------------------------
		// Public API
		//--------------------------------------------------------------------
		
		/**
		 * Indicates if <code>a</code> array collection contains 
		 * passed-in <code>o</code> element.
		 * 
		 * @param o Element to search
		 * @param a Array collection to search in
		 * @return <code>true</code> if passed-in <code>o</code> is in array.
		 */
		public static function contains( o : *, a : Array ) : Boolean
		{
			return ( a.indexOf( o ) != -1 );
		}
		
		/**
		 * Remove passed-in <code>o</code> value from passed-in 
		 * <code>a</code> array collection.
		 * 
		 * <p>All occurances of {@code value} are removed.</p>
		 * 
		 * @param o Element to remove
		 * @param a Array collection to search in
		 */
		static public function remove( o : *, a : Array ) : void
		{
			var l : uint = a.length;
			
			for( var i : Number = l; i > -1; i -= 1 )
			{
				if( a[i] === o ) a.splice( i, 1 );
			}
		}

		/**
		 * Removes element at <code>i</code> index from passed-in
		 * <code>a</code> array collection.
		 * 
		 * @param i Index to remove
		 * @param a Array collection to search in
		 * @param flag ( optional ) <code>true</code> to return 
		 * removed element, 
		 * <code>false</code> to return source array.
		 */
		public static function removeAt( i : Number, a : Array, 
			flag : Boolean ) : *
		{
			var o : * = a.splice( i, 1 );
			return ( flag ) ? o : a;
		}

		/**
		 * Removes the first occurance of the given <code>o</code> out 
		 * of the passed-in <code>a</code> array collection.
		 * 
		 * @param o Element to remove
		 * @param a Array collection to search in
		 * @param flag ( optional ) <code>true</code> to return removed 
		 * element, <code>false</code> to return source array.
		 */
		public static function removeFirst( o : *, a : Array, flag : Boolean ) 
			: *
		{
			var l : int = a.length;
			var index : Number = -1;
			
			for ( var i : int = 0; i < l ; i += 1 ) 
			{
				if ( a[i] === o )
				{
					a.splice( i, 1 );
					index = i;
					break;
				}
			}
			
			return ( flag ) ? index : a;
		}

		/**
		 * Removes the last occurance of the given <code>o</code> out of the 
		 * passed-in <code>a</code> array collection.
		 * 
		 * @param o Element to remove
		 * @param a Array collection to search in
		 * @param flag ( optional ) <code>true</code> to return 
		 * removed element, <code>false</code> to return source array.
		 */
		public static function removeLast( o : *, a : Array, 
			flag : Boolean ) : *
		{
			var l : int = a.length;
			var index : Number = -1;
			
			while( --l > -1 )
			{
				if( a[l] === o )
				{
					a.splice( l, 1 );
					index = l;
					break;
				}
			}
			
			return ( flag ) ? index : a;
		}
		
		/**
		 * Shuffles the passed-in <code>a</code> array collection.
		 * 
		 * @param array Array collection to shuffle
		 */
		public static function shuffle( a : Array ) : Array
		{
			var l : int = a.length; 
			var r : int;
			var temp : *;
			
			for ( var i : int = l - 1; i >= 0 ; i -= 1 ) 
			{ 
				r = Math.floor( Math.random( ) * l ); 
				temp = a[i];
				a[i] = a[r];
				a[ r ] = temp;
			} 
			
			return a;
		}

		/**
		 * Swaps value at index <code>i</code> with value at 
		 * index <code>j</code> in the passed-in <code>a</code> array.
		 * 
		 * @param array Array instance
		 * @param i Index of the first value
		 * @param j Index of the second value
		 */
		public static function swap( i : int, j : int, a : Array ) 
			: Array
		{
			if( !a || a.length < 2 ) return a;
			
			var l : int = a.length;
			
			if( i > -1 && i < l && j > -1 && j < l )
			{
				var tmp : * = a[ i ];
				a[ i ] = a[ j ];
				a[ j ] = tmp;
			}
			
			return a;
		}

		/**
		 * Indicates if the 2 passed arrays are equal or not.
		 * 
		 * @param a1 First Array collection
		 * @param a2 Second Array collection
		 * 
		 * @return <code>true</code> if 2 arrays are equals, 
		 * otherwise <code>false</code>
		 */
		public static function areEqual( a1 : Array, a2 : Array ) : Boolean
		{
			if ( a1.length != a2.length ) return false;
			
			var l : int = a1.length;
			for ( var i : int = 0; i < l ; i += 1 )
			{
				if ( a1[i] !== a2[i] ) return false;
			}
			return true;
		}

		/**
		 * Makes all array elements unique and returns array.
		 * 
		 * <p>Original array is modified.
		 */
		public static function unique( a : Array ) : Array
		{
			var l : int = a.length;
			
			for( var i : int = 0; i < l ; i += 1)
			{
				for( var j : int = ( i + 1 ); j < l ; j += 1 )
				{
					if( a[i] === a[j] ) a.splice( j, 1 );
				}	
			} 
			
			return a;
		}

		/**
		 * Returns passed-in <code>a</code> Array content at random 
		 * index.
		 */
		public static function getRandomSlot( a : Array ) : *
		{
			if( !a || a.length < 1 ) return null;
			
			var index : Number = Random.nextInt( a.length - 1 );
			
			if( a[ index ] == undefined )
			{
				FeverDebug.ERROR( "Index out of bounds" );
				index = 0;
			}
			
			return a[ index ];
		}

		/**
		 * Returns a clone array of passed-in <code>a</code> instance.
		 */
		public static function clone( a : Array ) : Array
		{
			return a.concat( );
		}
		
				
		//--------------------------------------------------------------------
		// Private implementations
		//--------------------------------------------------------------------		
		
		/** @private */
		public function ArrayUtil( access : PrivateConstructorAccess ) 
		{
		}
	}
}


internal class PrivateConstructorAccess 
{
}